package org.languageguide.readings;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import org.languageguide.storage.DBConnector;

public class DefinitionProcessor {
	
	StringBuilder text;
	List<Definition> definitions;
	Integer id;
	String target;
	
	public DefinitionProcessor(Integer id, String text, String target){
		definitions = new ArrayList<Definition>();
		this.id = id;
		this.target = target;
		loadDefinitions();
		this.text = new StringBuilder(text);
	}
	
	
	public void loadDefinitions(){
		String sql = "SELECT * FROM `ReadingDefinitions` RIGHT JOIN `ReadingDefinitionTranslation` ON ReadingDefinitions.Id = ReadingDefinitionTranslation.DefinitionId AND ReadingDefinitions.SortingOrder = ReadingDefinitionTranslation.SortingOrder WHERE TargetLanguage = ? AND ReadingId = ? Order BY Id, ReadingDefinitions.SortingOrder ASC";
		DBConnector connector = DBConnector.getInstance();
		Connection connection = connector.getConnection(false);
		try {
			PreparedStatement stmt = connection.prepareStatement(sql);
			stmt.setString(1, target);
			stmt.setInt(2, id);
			ResultSet set = stmt.executeQuery();
			while (set.next()){
				Definition def = new Definition(set);
				if (def.hasBody()){
					definitions.add(def);
				}
			}
		
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		finally{
			//if (connector != null){
				connector.close(connection);
			//}
		}
		
	}
	
	private int getStartOfSpan(int loc){
		loc--;
		char character = text.charAt(loc);
		while (character != '<'){
			loc--;
			character  = text.charAt(loc);
		}
		return loc;
	}
	
	public void processPhrase(Definition def, String phrase, int start){
		StringTokenizer st = new StringTokenizer(phrase); 
		String token = st.nextToken();
		String toSearchFor = ">" + token + "</span>";
		int location = text.indexOf(toSearchFor, start);
		if (location == -1){
			System.out.println("error not found:" + phrase);
			return;
		}
		int startSpan = getStartOfSpan(location);	
		//boolean failure = false;
		//int nextSpanEnd = -1;
		int nextSpanEndEnd = location + toSearchFor.length();
		while (st.hasMoreTokens()){
			token = st.nextToken();
			//int spanEnd = location + toSearchFor.length();
			int nextSpanBegin = text.indexOf("<", nextSpanEndEnd);
			int nextSpanBeginEnd = text.indexOf(">", nextSpanBegin);
			int nextSpanEndBegin = text.indexOf("<", nextSpanBeginEnd);
			nextSpanEndEnd = text.indexOf(">", nextSpanEndBegin) + 1;
			String nextWord = text.substring(nextSpanBeginEnd + 1, nextSpanEndBegin);
			if (!token.equals(nextWord)){
				processPhrase(def, phrase, location + 1);
				return;
			}
		}
		
		//everything matched up
		String textToWrap = text.substring(startSpan, nextSpanEndEnd);
		text.replace(startSpan, nextSpanEndEnd, def.generateDefLink(textToWrap));
		
		
	}
	
	boolean wordGranularity = true;
	int location = -1;
	public void process() throws Exception{
		StringBuilder definitionDivs = new StringBuilder();
		for (Definition def: definitions){
			boolean hasBody = def.hasBody();
			String matchingText = def.getMatchingText();
			Integer occurrence = def.getOccurrence();
			definitionDivs.append(def.getBodyDiv());
			if (wordGranularity){
				StringTokenizer st = new StringTokenizer(matchingText, " ");
				if (st.countTokens() > 1){
					processPhrase(def, matchingText, 0);
				}
				else{
					String toSearchFor = ">" + matchingText + "</span>";
					//System.out.println("matchingText" + matchingText);
					occurrence = occurrence - 1;
					int location = text.indexOf(toSearchFor);
					while (location != -1 && occurrence != 0){
						location = text.indexOf(">" + matchingText + "</span>", location + 1);
						occurrence = occurrence - 1;
					}
					if (location != -1){
						System.out.println("matchingText" + matchingText + " " + location);
						int startSpan = getStartOfSpan(location);
						int endSpan = location + toSearchFor.length();
						String textToWrap = text.substring(startSpan, endSpan);
						text.replace(startSpan, endSpan, def.generateDefLink(textToWrap));
					}
					else{
						System.out.println("Not found: " + matchingText);
					}
				}
			}
			else{
				while (occurrence != 0){
					location = text.indexOf(" " + matchingText, location + 1);
					occurrence = occurrence - 1;
				}
				if (location != -1){
					//if word granularity, find begining and end of word span
					text.replace(location, location + matchingText.length() + 1, def.generateDefLink());
				}
				else{
					throw new Exception("malformed def");
				}
			}
		}
		text.append(definitionDivs);
	}
	
	public String getText(){
		return text.toString();
	}
	
	public void save(){
		org.languageguide.storage.DBConnector connector = org.languageguide.storage.DBConnector.getInstance();
		java.sql.Connection connection = connector.getConnection(false);
		try{
			String sql = "Insert Into TranslatedReading (ReadingId, TargetLanguage, Text, PublishedText) VALUES (?, ?, ?, ?)";
			PreparedStatement statement = connection.prepareStatement(sql);
			statement.setInt(1, id);
			statement.setString(2, target + "-test");
			String textToPublish = text.toString();
			statement.setString(3, textToPublish);
			statement.setString(4, textToPublish);
			statement.executeUpdate();
		}
		catch (java.sql.SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println("translation save failure:" + e.getMessage());
			/*final java.io.Writer result = new java.io.StringWriter();
		    final java.io.PrintWriter printWriter = new java.io.PrintWriter(result);
	    	e.printStackTrace(printWriter);*/



		} 
		finally{
			//			cat.cleanUpStatements();
			if (connector != null){
				connector.close(connection);
			}
		}
	}
	
	public void saveUpdate(){
		org.languageguide.storage.DBConnector connector = org.languageguide.storage.DBConnector.getInstance();
		java.sql.Connection connection = connector.getConnection(false);
		try{
			String sql = "Update TranslatedReading Set PublishedText = ? WHERE ReadingId = ? AND TargetLanguage = ?";
			PreparedStatement statement = connection.prepareStatement(sql);
			statement.setString(1, text.toString());
			statement.setInt(2, id);
			statement.setString(3, target);			
			statement.executeUpdate();
		}
		catch (java.sql.SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println("translation save failure:" + e.getMessage());
			/*final java.io.Writer result = new java.io.StringWriter();
		    final java.io.PrintWriter printWriter = new java.io.PrintWriter(result);
	    	e.printStackTrace(printWriter);*/

		} 
		finally{
			//			cat.cleanUpStatements();
			if (connector != null){
				connector.close(connection);
			}
		}
	}
	
	public static void main(String[] args) {
		//addReading("My Name is Barney", "singlurity", "fr");
		//addParagraghTagsIfMissing("Virtually all of the few known candy poisoning incidents involved parents who poisoned their own children's candy.\r\n\r\nGames and other activities\r\nApple bobbing is a game often played in connection with Halloween.");
		//storeSentencesToTranslate(26);
		//loadSentenceTranslations(26, "fr");
		//new ReadingManager().generateAndSaveReading(78);

		//new ReadingManager().storeWordWrappedText(73);
		//	new ReadingManager().storeSentenceWrappedText(76);
		String text = new ReadingManager().generateReadingWithTranslation(73, "fr");
		DefinitionProcessor processedText = new DefinitionProcessor(73, text, "fr");
		try {
			processedText.process();
			processedText.saveUpdate();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("" + processedText.getText());
	//new DefinitionProcessor().generateAndSaveReading(78, "es");
		
	 
		// 
	}
	
	

}
